﻿using System;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;

using vJine.Core.IO.Xml;

namespace vJine.Core {
    [Serializable]
    [AppConfig("vJine.Net/AppContext")]
    public partial class AppContext {
        [XmlAttribute]
        public string Name { get; set; }
        [XmlAttribute]
        public string Version { get; set; }
        [XmlAttribute]
        public string Author { get; set; }
        [XmlAttribute]
        public string Company { get; set; }
        [XmlAttribute]
        public string CopyRight { get; set; }
        [XmlElement]
        public string SupportURL { get; set; }

        [XmlArray]
        public ModuleCollection Modules { get; set; }
        [XmlArray]
        public SequenceCollection Sequences { get; set; }

        public AppContext() {
            Call<Assembly, string> GetAssemblyByName = (string Name) => {
                Assembly[] As = AppDomain.CurrentDomain.GetAssemblies();
                for (int i = 0; i < As.Length; i++) {
                    if (As[i].FullName == Name) {
                        return As[i];
                    }
                }

                if (this.Modules == null || this.Modules.Count == 0) {
                    return null;
                }
                for (int i = 0; i < this.Modules.Count; i++) {
                    if (this.Modules[i].Assembly != null && this.Modules[i].Assembly.FullName == Name) {
                        return this.Modules[i].Assembly;
                    }
                }

                return null;
            };

            AppDomain.CurrentDomain.AssemblyResolve +=
                new ResolveEventHandler((object sender, ResolveEventArgs args)=> {
                    return GetAssemblyByName(args.Name) ?? null;
                });
        }

        public static AppContext Create() {
            return AppConfig<AppContext>.Get();
        }

        public static AppContext Create(string section_name) {
            return AppConfig<AppContext>.Get(section_name);
        }

        #region Sequence
        public void Run() {
            string default_name = this.Sequences.Default;
            if (string.IsNullOrEmpty(default_name)) {
                if (this.Sequences.Count > 0) {
                    default_name = this.Sequences[0].Name;
                }
            }

            this.Run(default_name);
        }

        public void Run(string Name) {
            Sequence S =
                this.Sequences.GetByName(Name);
            if (S == null) {
                throw new CoreException("Sequence[{0}]@[{1}] 未找到", Name, this.Name);
            }

            this.Load();

            for (int i = 0, len = S.Intances.Count; i < len; i++) {
                Instance _instance_i = S.Intances[i];

                _instance_i.Execute(S.Intances);
            }
        }
        #endregion Sequence

        bool IsLoaded = false;
        void Load() {
            if (this.IsLoaded) {
                return;
            }

            if (this.Modules == null) {
                return;
            }

            for (int i = 0, len = this.Modules.Count; i < len; i++) {
                this.Modules[i].Load(AppDomain.CurrentDomain);
            }

            this.IsLoaded = true;
        }
    }
}
